/*
@title: tower_of_hanoi
@description: Tower of Hanoi is a simple and retro puzzle game developed by nicholasz2510. The objective of the game is to move a set of rings from one post to another, following specific rules, to recreate the stack by ascending size on the final post.
@author: nicholasz2510
@tags: ['retro']
@addedOn: 2022-10-02
*/


// SPRITES
const post = "p";
const loop0 = "0";
const loop1 = "1";
const loop2 = "2";
const selected = "s"; 
setLegend(
  [ post, bitmap`
................
.......CL.......
.......CL.......
.......CL.......
.......CL.......
.......CL.......
.......CL.......
.......CL.......
.......CL.......
.......CL.......
.......CL.......
.......CL.......
.......CL.......
.......CL.......
.CCCCCCCCCCCCCC.
................`],
  [ loop0, bitmap`
................
................
................
................
................
................
................
................
................
................
................
...4444444444...
..4..........4..
...4444444444...
................
................`],
  [ loop1, bitmap`
................
................
................
................
................
................
................
.....555555.....
....5......5....
.....555555.....
................
................
................
................
................
................`],
  [ loop2, bitmap`
................
................
................
......8888......
.....8....8.....
......8888......
................
................
................
................
................
................
................
................
................
................`],
  [ selected, bitmap`
................
.......3L.......
.......3L.......
.......3L.......
.......3L.......
.......3L.......
.......3L.......
.......3L.......
.......3L.......
.......3L.......
.......3L.......
.......3L.......
.......3L.......
.......3L.......
.33333333333333.
................`]
);
const loops = [loop0, loop1, loop2];
const blank = map`
...
...`;
const level = map`
ppp
...`;


// STATE
let indexSelected;
let posts;
let types;
let moveCount;
let started = false;
let numRings = 2;

// ON RUN
setMap(blank);
addText("ASD = source", {y: 4});
addText("JKL = destination", {y: 6});
addText("any key to start", {y: 8});

function reset() {
  clearText();
  setMap(level);
  for (let i = 0; i < numRings; i++) {
    addSprite(0,0,loops[i]);
  }
  select(0);
  posts = [[...Array(numRings).keys()].reverse(), [], []];
  types = posts[0].map(x => String(x));
  moveCount = 0;
  started = true;
}

function updateMoveCount() {
  
}

function clearSelection() {
  let tiles = getAll("s");
  for (let i = 0; i < tiles.length; i++) {
    let currSprite = tiles[i];
    currSprite.type = "p";
  }
}

function select(j) {
  let currTile = getTile(j,0);
  for (let i = 0; i < currTile.length; i++) {
    let currSprite = currTile[i];
    if (currSprite.type == "p") {
      currSprite.type = "s";
    }
  }
  indexSelected = j;
}

function move(j, k) {
  if (j == k || j == -1 || posts[j][posts[j].length - 1] > posts[k][posts[k].length - 1] || posts[j].length == 0) {
    return;
  }
  
  let removed = posts[j].pop();
  posts[k].push(removed);
  let movedSprite = getFirst(types[removed]);
  movedSprite.x = k;
  indexSelected = -1;
  moveCount++;
}


// MOVE FROM
onInput("a", () => {
  if (!started) {
    return;
  }
  clearSelection();
  select(0);
});

onInput("s", () => {
  if (!started) {
    return;
  }
  clearSelection();
  select(1);
});

onInput("d", () => {
  if (!started) {
    return;
  }
  clearSelection();
  select(2);
});


// MOVE TO
onInput("j", () => {
  if (!started) {
    return;
  }
  move(indexSelected, 0);
  clearSelection();
});

onInput("k", () => {
  if (!started) {
    return;
  }
  move(indexSelected, 1);
  clearSelection();
});

onInput("l", () => {
  if (!started) {
    return;
  }
  move(indexSelected, 2);
  clearSelection();
});


afterInput(() => {
  if (!started) {
    reset();
  }
  clearText();
  
  if (posts[2].length == numRings) {
    addText("win!", { y: 12, color: color`3` });
    started = false;
    numRings = 3;
  }

  addText("Move count: " + moveCount, { y: 8});
});
